#include "h01.h"

#include "accelerometer.h"
#include "battery.h"
#include "display.h"
#include "iap.h"
#include "iic.h"
#include "power.h"
#include "rtc.h"
#include "usb.h"
#include "vx.h"

#define	SIGN_SAV		0x55aa55aa

#define SYSCTRL			((uint)0xE000ED10)
#define DEEP_SLEEP		((uint)0x00000004)

static void initClock(uint hclk){
	SystemCoreClockUpdate();
	RCC_HCLKConfig(hclk);
	RCC_APB1PeriphClockCmd(
		RCC_APB1Periph_BKP|
		RCC_APB1Periph_I2C2|
		RCC_APB1Periph_PWR,ENABLE);
	RCC_APB2PeriphClockCmd(
		RCC_APB2Periph_AFIO|
		RCC_APB2Periph_GPIOA|
		RCC_APB2Periph_GPIOB|
		RCC_APB2Periph_GPIOC|
		RCC_APB2Periph_TIM1,ENABLE);
	PWR_BackupAccessCmd(ENABLE);
}
static void initNVIC(void){
	initVecTable();
	//NVIC_SetVectorTable(NVIC_VectTab_FLASH,0);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	NVIC_InitTypeDef n;
	n.NVIC_IRQChannel=EXTI0_IRQn;		// WKUP
	n.NVIC_IRQChannelPreemptionPriority=3;
	n.NVIC_IRQChannelSubPriority=1;
	n.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&n);
	n.NVIC_IRQChannel=EXTI15_10_IRQn;	// GSINT
	n.NVIC_IRQChannelPreemptionPriority=3;
	n.NVIC_IRQChannelSubPriority=1;
	n.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&n);
	n.NVIC_IRQChannel=I2C2_EV_IRQn;		// IIC2
	n.NVIC_IRQChannelPreemptionPriority=0;
	n.NVIC_IRQChannelSubPriority=0;
	n.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&n);
	n.NVIC_IRQChannel=ADC1_2_IRQn;		// ADC
	n.NVIC_IRQChannelPreemptionPriority=3;
	n.NVIC_IRQChannelSubPriority=1;
	n.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&n);

	EXTI_DeInit();
	EXTI_InitTypeDef x;
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,PINSRC_WKUP);
	x.EXTI_Line	  =EXTI_WKUP;
	x.EXTI_Mode	  =EXTI_Mode_Interrupt;
	x.EXTI_Trigger=EXTI_Trigger_Rising;
	x.EXTI_LineCmd=ENABLE;
	EXTI_Init(&x);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,PINSRC_GSINT);
	x.EXTI_Line	  =EXTI_GSINT;
	x.EXTI_Mode	  =EXTI_Mode_Interrupt;
	x.EXTI_Trigger=EXTI_Trigger_Rising;
	x.EXTI_LineCmd=ENABLE;
	EXTI_Init(&x);
	NVIC_SetPriority(SysTick_IRQn,1);
}
static void initGPIO(void){
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);   //Use SWD
	GPIO_InitTypeDef g;
	g.GPIO_Speed=GPIO_Speed_50MHz;

	g.GPIO_Pin	=PIN_CHIN;
	g.GPIO_Mode	=GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&g);
	g.GPIO_Pin	=PIN_CHOUT;
	g.GPIO_Mode	=GPIO_Mode_Out_OD;
	GPIO_SetBits(GPIOA,g.GPIO_Pin);
	GPIO_Init(GPIOA,&g);
	g.GPIO_Pin	=PIN_Y0_Y2;
	g.GPIO_Mode	=GPIO_Mode_Out_PP;
	GPIO_ResetBits(GPIOA,g.GPIO_Pin);
	GPIO_Init(GPIOA,&g);
    g.GPIO_Pin	=PIN_WKUP;
    g.GPIO_Mode	=GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA,&g);

    g.GPIO_Pin	=PIN_GSINT;
    g.GPIO_Mode	=GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB,&g);
	g.GPIO_Pin	=PIN_Y3_Y9;
	g.GPIO_Mode	=GPIO_Mode_Out_PP;
	GPIO_ResetBits(GPIOB,g.GPIO_Pin);
	GPIO_Init(GPIOB,&g);
	g.GPIO_Pin	=PIN_I2C;
	g.GPIO_Mode	=GPIO_Mode_AF_OD;
	GPIO_SetBits(GPIOB,g.GPIO_Pin);
	GPIO_Init(GPIOB,&g);

	g.GPIO_Pin	=PIN_VOLT;
	g.GPIO_Mode	=GPIO_Mode_AIN;
	GPIO_Init(GPIOC,&g);
	g.GPIO_Pin	=PIN_X0_Y9;
	g.GPIO_Mode	=GPIO_Mode_Out_OD;
	GPIO_SetBits(GPIOC,g.GPIO_Pin);
	GPIO_Init(GPIOC,&g);
}
static void restore(void){
	ushort ex=BKP_ReadBackupRegister(BACKUP_EXTRA);
	savRam.timeOfs=BKP_ReadBackupRegister(BACKUP_TMOFSL)+
		(BKP_ReadBackupRegister(BACKUP_TMOFSH)<<16);
	curSteps=BKP_ReadBackupRegister(BACKUP_STEPS)+((ex&1)<<16);
	ex=BKP_ReadBackupRegister(BACKUP_BOOTS);
	BKP_WriteBackupRegister(BACKUP_BOOTS,ex+1);
	if(savRom.signSav==SIGN_SAV)
		savRam.accBase=savRom.accBase;
	else savRam.signSav=SIGN_SAV;
}

//------------------------------------------------------------------------------

void booting(void){
	init(RCC_SYSCLK_Div512);
	watchdogOn();
	meterOn();
	if(powerSignal())
		PWR_EnterSTANDBYMode();		
	meterOff();
	waitRTC();
	RCC_HCLKConfig(RCC_SYSCLK_Div2);
	initAccelerometer();
	status=getStatus();
}
void init(uint hclk){
	initClock(hclk);
	initRTC();
	initNVIC();
	initGPIO();
	restore();
	*(uint*)SYSCTRL&=~DEEP_SLEEP;
}
void silent(ubyte stt){
	displayOff();
	while(status==stt){
		PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFE);
		SystemInit();
		RCC_HCLKConfig(RCC_SYSCLK_Div4);
		ubyte s=getStatus();
		status=s==STATUS_TAP?STATUS_PEDOMETER:s;
	}
}
void watchdogOn(void){
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	IWDG_SetPrescaler(IWDG_Prescaler_256);
	IWDG_SetReload(0x0fff);
	IWDG_ReloadCounter();
	IWDG_Enable();
}